home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
lisp
/
eulisp
/
mpfeel.lha
/
MPFeel
/
Modules
/
elopt.em
< prev
next >
Wrap
Lisp/Scheme
|
1992-10-06
|
11KB
|
314 lines
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; EuLisp Module Copyright (C) University of Bath 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; $Id:$
;
; $Log:$
;
(defmodule elopt
(standard
loops
trandecl
tranutil) ()
(deflocal ModuleName)
(deflocal bblist)
(deflocal endsbb-table (make-table))
(deflocal instr-type-table (make-table))
(deflocal opt-code-stream)
(deflocal label-tab)
(deflocal def-use-table)
(defstruct opt-basic-block ()
(
;; first-ins is the list on instructions which make up the basic block
;; last-ins is the last instruction in the basic block
;; next-blk is a list of basic blocks which may follow this one (max 2)
;; prev-blk is a list of basic block which may preceed this one
(first-ins initform nil initarg first-ins accessor first-ins)
(last-ins initform nil initarg last-ins accessor last-ins)
(next-blk initform nil initarg next-blk accessor next-blk)
(prev-blk initform nil initarg prev-blk accessor prev-blk)
(gen initform nil initarg gen accessor gen)
(kill initform nil initarg kill accessor kill)
)
constructor make-opt-basic-block)
(defmethod generic-prin ((x opt-basic-block) s)
(format s "#<opt-basic-block:~u~%" x)
(format s "~tfirst: ~a last:~a~%" (first-ins x) (last-ins x))
(for (setq i (next-blk x)) i (setq i (cdr i))
(format s "~t~tnext ~u" (car i)))
(format s "~%")
(for (setq i (prev-blk x)) i (setq i (cdr i))
(format s "~t~tprev ~u" (car i)))
(format s "~%gen: ~a~%" (gen x))
(format s "kill: ~a>~%" (kill x)))
(defmethod generic-write ((x opt-basic-block) s)
(format s "#<opt-basic-block:~u~%" x)
(format s "~tfirst: ~a last:~a~%" (first-ins x) (last-ins x))
(for (setq i (next-blk x)) i (setq i (cdr i))
(format s "~t~tnext ~u" (car i)))
(format s "~%")
(for (setq i (prev-blk x)) i (setq i (cdr i))
(format s "~t~tprev ~u" (car i)))
(format s "~%gen: ~a~%" (gen x))
(format s "kill: ~a>~%" (kill x)))
(defcondition elopt-error ())
(defun fourth (x) (car (cdr (cdr (cdr x)))))
(defun third (x) (car (cdr (cdr x))))
(defun second (x) (cadr x))
(defun first (x) (car x))
(defun table-ref-or-bust (table slot)
(let ((x (table-ref table slot)))
(if x x
(error "table-ref-or-bust failed to find a value" elopt-error))))
(defun optimise (a)
(opt-aux (copy-list a)))
(defun opt-aux (a)
(let ((args (code-list a)))
(if (eq (caar args) 'entry)
(opt-entry a)
(error "Does not look like a command" elopt-error))
(mapc opt-aux (enclosed-blocks a))))
;;; OK, given something which looks like
;;; ((entry name nargs results) (load...) (store...) (...) (...) (...))
;;; we split it up into a list of basic blocks
(defun opt-entry1 (block)
(cond ((null block) nil)
((table-ref endsbb-table (caar block))
(let* ((temp (cdr block)) ; hold the list after the cut
(current-bb (make-opt-basic-block 'first-ins temp)))
(setf (last-ins (car bblist)) (car block))
(setq bblist (cons current-bb bblist))
((setter cdr) block nil) ; cut it
(opt-entry1 temp))) ; cdr down the rest of the list
((and (not (null (cdr block))) ; A label starts a block
(eq (caadr block) 'label))
(let* ((temp (cdr block)) ; hold the list after the cut
(current-bb (make-opt-basic-block 'first-ins temp)))
(setf (last-ins (car bblist)) (car block))
(setq bblist (cons current-bb bblist))
((setter cdr) block nil) ; cut it
(opt-entry1 temp)))
(t (opt-entry1 (cdr block)))))
(defun opt-entry (block1)
(let ((current-bb (make-opt-basic-block 'first-ins block1)))
(setq bblist (cons current-bb nil))
(setq use-def-table (make-table))
(opt-entry1 block1)
;; Fix up last block - it might be null if last instruction is a null,
;; otherwise it needs to have last-ins set
(if (null (first-ins (car bblist)))
(setq bblist (cdr bblist))
(setf (last-ins (car bblist))
(car (last-pair (first-ins (car bblist))))))
;; bblist is now a reversed list of basic blocks
(setq bblist (reverse bblist))
;; set up the tempory table which joins labels to basic blocks
(setuplabeltable)
;; now fix up the pointers which link the basic blocks
(fixlinks)
(setup-def-use bblist)
(format t "~a~%" bblist)))
(defun setup-def-use (bblist)
(if (null bblist) nil
(progn
(setup-genkill1 (car bblist))
(setup-def-use (cdr bblist)))))
(defun setuplabeltable ()
(setq label-tab (make-table))
(add-ent bblist))
(defun add-ent1 (x bblock) ;x is a list of instructions
(if (eq (caar x) 'label)
((setter table-ref) label-tab (cadar x) bblock)
nil))
(defun add-ent (bbl)
(if (null bbl) nil
(progn
(add-ent1 (first-ins (car bbl)) (car bbl))
(add-ent (cdr bbl)))))
(defun fixlinks ()
(fixlinks1 bblist)
(fixlinks2 bblist))
;; Given bblist, a list of basic blocks, we construct the list of
;; following blocks. The first part is trivial, as we only need
;; to add the next bblock on
(defun fixlinks1 (bbl)
(if (null bbl) nil
(let* ((ins (last-ins (car bbl)))
(endtype (table-ref endsbb-table (car ins))))
;; The trivial part - join to next blockf unless it is a jump
(if (or (null (cdr bbl)) (eq (car ins) 'jump)) nil
((setter next-blk) (car bbl) (cons (cadr bbl) (next-blk (car bbl)))))
;; The slightly less trivial bit - join to other blocks
(if (eq endtype 'ajump)
((setter next-blk) (car bbl)
(cons (table-ref-or-bust label-tab
(if (eq (car ins) 'jump)
(cadr ins)
(fourth ins)))
(next-blk (car bbl))))
nil)
(fixlinks1 (cdr bbl)))))
;; set up the back pointers
(defun fixlinks2 (bbl)
(if (null bbl) nil
(progn
(for (setq i (next-blk (car bbl))) (not (null i)) (setq i (cdr i))
((setter prev-blk) (car i) (cons (car bbl) (prev-blk (car i)))))
(fixlinks2 (cdr bbl)))))
(defun setup-def-use-table (bbl)
(if (null bbl) nil
(progn
(setup1-def-use-table (first-ins (car bbl)))
(setup-def-use-table (cdr bbl)))))
;; Setup the list of registers which are generated and killed
;; by this basic block
(defun setup-genkill1 (bb)
(let ((gk (genkill (cons nil nil) (first-ins bb))))
(setf (gen bb) (car gk))
(setf (kill bb) (cdr gk))))
;; return a cons cell. CAR is a list of 'gen' registers, CDR is a list
;; of 'killed' registers, insl is an instruction list
(defun genkill (res insl)
(if (null insl) res
(let ((command (caar insl)) ;Elvira Instruction
(args (cdar insl)) ;Its arguements
(genl (car res)) ;Generated definitions
(killl (cdr res))) ;Killed definitions
(cond
((eq command 'alloca)) ;takes a number
((eq command 'apply) ;o1=apply(i1,i2)
(setq killl (addmember killl (car args)))
(setq killl (addmember killl (cadr args)))
(setq genl (addmember genl 'o1)))
((eq command 'begin-let/cc)) ;no parameters
((eq command 'begin-unwind-protect)
(setq killl (addmember killl (car args))))
((eq command 'begin-with-handler)
(setq killl (addmember killl (car args))))
((eq command 'bind)) ;need to think about this one
((eq command 'dealloca)) ;takes a number
((eq command 'entry)) ;Should use the initial regs
((eq command 'end-let/cc)) ;no parameters
((eq command 'end-unwind-protect)) ;no parameters
((eq command 'end-with-handler)) ;no parameters
((eq command 'function)) ;module,name,num-args
((eq command 'jump)) ;label
((eq command 'jumpeq) ;reg reg label. 2nd reg can be 'nil
(setq killl (addmember killl (car args)))
(setq killl (addmember killl (cadr args))))
((eq command 'return)
(setq killl (addmember killl 'o1))) ;need to think about this one
((eq command 'unbind))
((eq command 'cons)
(setq killl (addmember killl (cadr args)))
(setq killl (addmember killl (caddr args)))
(setq genl (addmember genl (car args))))
((eq command 'gctrap)) ;does not effect usage
((eq command 'label)) ;does not effect usage
((eq command 'link)
(cond
((eq (car args) 'self) nil)
((symbolp (car args)) (break))
((eq (caar args) 'local)
(setq killl (killmultiple killl (cadr args)))
(setq genl (addmember genl 'o1)))
((eq (caar args) 'nonlocal)
(setq killl (killmultiple killl (cadr args)))
(setq genl (addmember genl 'o1)))
((eq (caar args) 'display))
(t (error "Unknown link" el2c-error))))
((eq command 'load)
(setq genl (addmember genl (car args)))
(setq killl (addopand killl (cadr args))))
((eq command 'store)
(setq killl (addmember killl (car args)))
(setq genl (addopand genl (cadr args))))
(t (format t "UNKNOWN(~a ~a);~%" command args)))
; cdr down the list
(genkill (cons genl killl) (cdr insl))
)))
(defun addopand (l opand)
l)
(defun addmember (list newmem)
(if (memq newmem list) list (cons newmem list)))
(defun killmultiple (list number)
(killmultiple1 list number '(i1 i2 i3 i4 i5 i6 i7 i8 i9)))
(defun killmultiple1 (list number regs)
(if (zerop number) list
(killmultiple1 (addmember list (car regs)) (binary-minus number 1)
(cdr regs))))
;; insl is a list of instructions
(defun setup1-def-use-table (insl)
(if (null insl) nil
(progn
(setup2-def-use-table (car insl) (cdar insl))
(setup1-def-use-table (cdr insl)))))
(defun setup2-def-use-table (ins opands)
(if (null opands) nil
(progn
(if (atom (car opands))
((setter table-ref) use-def-table (car opands)
(cons ins (table-ref use-def-table (car opands))))
(error (format nil "!Atom in setup2-def-use-table ~a~%" elopt-error)))
(setup2-def-use-table ins (cdr opands)))))
(defun init-bbs-table ()
((setter table-ref) endsbb-table 'jump 'ajump)
((setter table-ref) endsbb-table 'jumpeq 'ajump)
((setter table-ref) endsbb-table 'jumpne 'ajump)
((setter table-ref) endsbb-table 'jumpgt 'ajump)
((setter table-ref) endsbb-table 'jumpgeq 'ajump)
((setter table-ref) endsbb-table 'jumple 'ajump)
((setter table-ref) endsbb-table 'jumpleq 'ajump)
((setter table-ref) endsbb-table 'entry t)
)
(init-bbs-table)
(setq fred '((entry fred)
(load o1 1)
(label 5)
(store o1 (display 1 2))
(jumpeq l1 nil 6)
(cons l1 i1 i2)
(load o1 4)
(label 6)
))
(defun try-it ()
(opt-entry (copy fred)))
(export optimise opt-code-stream)
)